# 装饰器-学习
import datetime
import functools

# def log(func):
#     @functools.wraps(func)
#     def wrapper(*args, **kw):
#         if 'a' in kw:
#             kw["a"]='hall'
#             print("A")
#         print('call %s():' % func.__name__)
#         return func(*args, **kw)

#     return wrapper


def log(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)

        return wrapper

    return decorator


@log("now")
def now(a=None):
    now = datetime.datetime.now().strftime('%Y-%m-%d')
    print(a, now)


now()
# now = log(text)(now)

################################
import time
def metric(fn):
    @functools.wraps(fn)
    def wrapper(*args,**kw):
        print('%s executed in %s ms' % (fn.__name__, datetime.datetime.now().strftime("%H:%M:%S")))
        return fn(*args,**kw)
    return wrapper


# 测试
@metric
def fast(x, y):
    time.sleep(0.0012)
    return x + y;

@metric
def slow(x, y, z):
    time.sleep(0.1234)
    return x * y * z;

f = fast(11, 22)
s = slow(11, 22, 33)
if f != 33:
    print('测试失败!')
elif s != 7986:
    print('测试失败!')


################################
def alog(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            print("start func")
            a = func(*args, **kwargs)
            print("end func")
            return a
        return wrapper
# 判断text是字符还是函数
    return {True: decorator, False: decorator(text)}[isinstance(text,str)]

# new = log(new)
@alog
def new():
    print("hello world")


# new = alog(text)(new)
@alog("bbb")
def newa():
    print("hello world!")


new()
newa()


class Foo(object):
    def __init__(self, func):
        self._func = func

    @property
    def __name__(self):
        print(self._func.__name__)

    @property
    def __doc__(self):
        print(self._func.__doc__)

    def __call__(self):
        print('class decorator runing')
        self._func()
        print('class decorator ending')


@Foo
def bar():
    """dddd"""
    print('bar')


bar()

#####################################
# 偏函数

# functools.partial()


int2 = functools.partial(int, base=2)

int2("1000000")

int2("1000", base=10)

max10 = functools.partial(max, 10)

max10(4, 5, 6)


def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
        print(f"args:{args}")
        print(f"********************************")
        print(f"kw:{kw}")
        return func(*args, **kw)

    return wrapper


@log
def numbera(num):
    print(f"num:{num}")


numbera(num=5)
